/* model */
import { ConnectorModuleComponentNameEnum, CreateConnectorDialogFieldNameEnum } from '@src/modules/connector/model';
import Field from '@model/entity/Field';
/* scss */
import '@src/modules/connector/view/list/components/create-dialog/index.scss';
/* vue */
// @ts-ignore
import { ComponentInstance, ComponentRenderProxy, defineComponent, PropType, watch, computed } from 'vue';
import { CommonComponentInstance } from '@model/VC';
import { CreateElement } from 'vue';
/* hooks */
import { useDialog } from '@hooks/useDialog';
/* util */
import { isFalsy, isObject } from '@src/util/type';
import Log from '@src/util/log';
import locales, { t } from '@src/locales';
import { getRootWindow } from '@src/util/dom';

type CreateConnectorDialogFormBuilderScopedSlotDataType = {
  field: Field;
  value: string[];
};
type FieldUpdateResult = {
  field: Field;
  newValue: any;
  oldValue: any;
};

export type ConnectorListViewCreateDialogProps = {
  disabled: boolean;
  title: string;
  value: Record<string, any>;
  visible: boolean;
};

export interface ConnectorListViewCreateDialogSetupState {}

export enum ConnectorListViewCreateDialogEmitEventNameEnum {
  Input = 'input',
  Close = 'close',
  Confirm = 'confirm',
}

export type ConnectorListViewCreateDialogInstance = ComponentInstance & ConnectorListViewCreateDialogSetupState;
export type ConnectorListViewCreateDialogVM = ComponentRenderProxy<ConnectorListViewCreateDialogProps> & CommonComponentInstance & ConnectorListViewCreateDialogInstance;

export default defineComponent({
  name: ConnectorModuleComponentNameEnum.ConnectorListViewCreateDialog,
  emits: [ConnectorListViewCreateDialogEmitEventNameEnum.Input, ConnectorListViewCreateDialogEmitEventNameEnum.Close, ConnectorListViewCreateDialogEmitEventNameEnum.Confirm],
  inject: ['setNeedLanguage'],
  props: {
    disabled: {
      type: Boolean as PropType<boolean>,
      default: false,
    },
    fields: {
      type: Array as PropType<Field[]>,
      default: () => [],
    },
    title: {
      type: String as PropType<string>,
      default: '',
    },
    value: {
      type: Object as PropType<Record<string, any>>,
      default: () => ({}),
    },
    visible: {
      type: Boolean as PropType<boolean>,
      default: false,
    },
    isShowSelectLanguage: {
      type: Boolean as PropType<boolean>,
      default: false,
    },
  },
  setup(props: ConnectorListViewCreateDialogProps, { emit }) {
    const { visible: insideVisible, showDialog, hideDialog } = useDialog();

    const formBuildComponentRef = 'FormBuilderComponent';

    const onDialogCloseHandler = () => {
      emit(ConnectorListViewCreateDialogEmitEventNameEnum.Close);
    };

    const onDialogConfirmHandler = () => {
      emit(ConnectorListViewCreateDialogEmitEventNameEnum.Confirm);
    };

    watch(
      () => props.visible,
      visible => {
        if (visible) {
          showDialog();
        } else {
          hideDialog();
        }
      },
      {
        immediate: true,
      }
    );

    // 多语灰度
    const isMultiLanguage = computed(() => {
      const RootWindow = getRootWindow(window);
      return RootWindow.grayAuth?.multiLanguage ?? false;
    });

    return {
      insideVisible,
      formBuildComponentRef,
      isMultiLanguage,

      showDialog,
      hideDialog,

      onDialogCloseHandler,
      onDialogConfirmHandler,
    };
  },
  methods: {
    cancel() {
      this.hideDialog();
      this.onDialogCloseHandler();
    },
    async confirm() {
      const formBuildComponent: Record<string, any> = this.$refs[this.formBuildComponentRef];
      if (isFalsy(formBuildComponent)) {
        Log.warn('[connector-create-dialog] FormBuilderComponent Does not exist');
        return;
      }

      const validated = await formBuildComponent.validate()

      if (isFalsy(validated)) {
        Log.warn('[connector-create-dialog] FormBuilderComponent validate failed')
        return
      }

      this.onDialogConfirmHandler();
    },
    /**
     * @description 获取属性列表
     * @return {Record<string, any>} 属性列表
     */
    getAttributes(): Record<string, any> {
      return {
        class: ConnectorModuleComponentNameEnum.ConnectorListViewCreateDialog,
        props: {
          title: this.title,
          show: this.insideVisible,
          appendToBody: true,
        },
        on: {
          'update:show': () => {
            this.hideDialog();
            this.onDialogCloseHandler();
          },
        },
      };
    },
    /**
     * @description: 更新事件
     * @param {FieldUpdateResult} param
     * @return {void}
     */
    update({ field, newValue }: FieldUpdateResult): void {
      const { fieldName } = field;
      console.log(field, newValue);
      if (!isObject(newValue)) newValue = newValue.trim();
      this.$emit(ConnectorListViewCreateDialogEmitEventNameEnum.Input, { fieldName, newValue });
    },
    /**
     * @description: 渲染表单作用域插槽
     * @return {VNode | null} 插槽或空
     */
    renderFormBuilderScopedSlot(h: CreateElement) {
      return {
        [CreateConnectorDialogFieldNameEnum.Name]: (data: CreateConnectorDialogFormBuilderScopedSlotDataType) => this.renderFormBuilderScopedSlotName(h, data),
        [CreateConnectorDialogFieldNameEnum.Description]: (data: CreateConnectorDialogFormBuilderScopedSlotDataType) => this.renderFormBuilderScopedSlotDescription(h, data),
      };
    },
    // 名称
    renderFormBuilderScopedSlotName(h: CreateElement, data: CreateConnectorDialogFormBuilderScopedSlotDataType) {
      const field = data?.field || {}
      field.defaultValueLanguage = this.value?.titleLanguage || {};
      const value = this.value?.titleLanguage?.[locales.locale] || data?.value;
      
      return (
        <form-item label={field.displayName} class="form-item-language">
          <form-text field={field} value={data?.value} onUpdate={(e: FieldUpdateResult) => this.syncLanguageUpdate(e, data, CreateConnectorDialogFieldNameEnum.TitleLanguage)} />
          { this.renderFormBuilderScopedSlotLanguage(field, value, CreateConnectorDialogFieldNameEnum.TitleLanguage, 'text') }
        </form-item>
      );
    },
    // 说明
    renderFormBuilderScopedSlotDescription(h: CreateElement, data: CreateConnectorDialogFormBuilderScopedSlotDataType) {
      const field = data?.field || {}
      field.defaultValueLanguage = this.value?.descLanguage || {};
      const value = this.value?.descLanguage?.[locales.locale] || data?.value;
      
      return (
        <form-item label={field.displayName} class="form-item-language">
          <form-textarea field={field} value={data?.value} onUpdate={(e: FieldUpdateResult) => this.syncLanguageUpdate(e, data, CreateConnectorDialogFieldNameEnum.DescLanguage)} />
          { this.renderFormBuilderScopedSlotLanguage(field, value, CreateConnectorDialogFieldNameEnum.DescLanguage, 'textarea') }
        </form-item>
      );
    },
    // 小地球
    renderFormBuilderScopedSlotLanguage(field: Field, value: string | string[], type: string, formType: string) {
      return (
        <base-select-language
          field={field}
          defaultOption={{
            formType: formType,
          }}
          defaultFormType={formType}
          defaultValue={value}
          defaultValueLanguage={field.defaultValueLanguage || {}}
          onSave={(e: any) => this.languageSave(e, field, type)}
        ></base-select-language>
      );
    },
    languageSave(data: any, field: Field, fieldName: string) {
      this.update({
        field: { fieldName },
        newValue: data,
        oldValue: '',
      });

      this.$nextTick(() => {
        // @ts-ignore
        this.$refs[this.formBuildComponentRef].rerender();
      });
    },
    syncLanguageUpdate(e: FieldUpdateResult, data: any, fieldName: string) {
      // 更新小地球
      if(e.newValue !== data) {
        this.update({
          field: { fieldName },
          newValue: {
            ...e.field.defaultValueLanguage,
            [locales.locale]: e.newValue
          },
          oldValue: ''
        });
      }
      
      this.update(e)
    },
  },
  render(h: CreateElement) {
    const attrs = this.getAttributes();
    const isScoped = (this.isShowSelectLanguage || this.setNeedLanguage) && this.isMultiLanguage;

    return (
      <base-modal {...attrs}>
        {this.insideVisible && <form-builder ref={this.formBuildComponentRef} fields={this.fields} value={this.value} onUpdate={this.update} scopedSlots={isScoped && this.renderFormBuilderScopedSlot(h)}></form-builder>}

        <div class="dialog-footer" slot="footer">
          <el-button disabled={this.disabled} onClick={this.cancel}>
            {t('common.base.cancel')}
          </el-button>

          <el-button type="primary" disabled={this.disabled} onClick={this.confirm}>
            {this.value?.id ? t('common.base.makeSure') : t('common.base.steps.next')}
          </el-button>
        </div>
      </base-modal>
    );
  },
});
